﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition;
using ExtendPropertyLib.WPF;
using ExtendPropertyLib;
using System.Collections.ObjectModel;
using ExORMDesginer.Models;
using System.Threading.Tasks;
using System.Windows;
using ExORMDesginer.Services;
using ExORMDesginer.UserControls;
using System.Windows.Input;
using ExORMDesginer.Helper;
using ExORMDesginer.UserControls.Dialogs;
using ExORMDesginer.RadWindow.Helper;
using Microsoft.Win32;
using System.IO;
using System.Collections.Specialized;
using DatabaseSchemaReader.DataSchema;
using System.Windows.Controls.Primitives;
using ExORMDesginer.Plugin;
namespace ExORMDesginer
{
    [Export(typeof(IShell))]
    public class MainViewModel : ViewModelBase<MainInfo> , IShell, IMainViewModel
    {
        [Import(typeof(IWindowManager))]
        private IWindowManager WindowManager { set; get; }

        private RadWindowManager RadWindow = new RadWindowManager();

        public override void OnDoCreate(ExtendObject item, params object[] args)
        {
            base.OnDoCreate(item, args);
            BuildUp(Model);
            InitView();
        
        }



        #region 属性
        /// <summary>
        /// 窗口管理者
        /// </summary>
        public IWindowManager Window
        {
            get
            {
                return RadWindow;
            }
        }
        public override string GetViewTitle()
        {
            return "Maxzhang's ORM Desginer";
        }
            
        public static ExtendProperty FindNameProperty = RegisterProperty<MainViewModel>(v => v.FindName);
        /// <summary>
        /// 查询表名和表描述‘名字
        /// </summary>
        public string FindName { set { SetValue(FindNameProperty, value); } get { return (string)GetValue(FindNameProperty); } }
        
        public static ExtendProperty IsBusyProperty = RegisterProperty<MainViewModel>(m => m.IsBusy);
        /// <summary>
        /// 同步显示loading....
        /// </summary>
        [Sync]
        public bool IsBusy { set{SetValue(IsBusyProperty, value);} get{return (bool)GetValue(IsBusyProperty);} }

       
        #endregion

        #region Display Data
        public static ExtendProperty DatabaseExplorerViewModelProperty = RegisterProperty<MainViewModel>(v => v.DatabaseExplorerViewModel);
        /// <summary>
        /// 数据库视图的ViewModel
        /// </summary>
        public DatabaseExplorerViewModel DatabaseExplorerViewModel { set { SetValue(DatabaseExplorerViewModelProperty, value); } get { return (DatabaseExplorerViewModel)GetValue(DatabaseExplorerViewModelProperty); } }

        
        public static ExtendProperty CodeGeneratorViewModelProperty = RegisterProperty<MainViewModel>(v => v.CodeGeneratorViewModel);
        /// <summary>
        /// 代码生成器视图的ViewModel
        /// </summary>
        public CodeGeneratorViewModel CodeGeneratorViewModel { set { SetValue(CodeGeneratorViewModelProperty, value); } get { return (CodeGeneratorViewModel)GetValue(CodeGeneratorViewModelProperty); } }

        
        public static ExtendProperty FilterDbSchemaViewModelProperty = RegisterProperty<MainViewModel>(v => v.FilterDbSchemaViewModel);
        /// <summary>
        /// 同步过滤视图的ViewModel
        /// </summary>
        public FilterDbSchemaViewModel FilterDbSchemaViewModel { set { SetValue(FilterDbSchemaViewModelProperty, value); } get { return (FilterDbSchemaViewModel)GetValue(FilterDbSchemaViewModelProperty); } }
        #endregion

        #region Method
    
        #region 视图操作
        /// <summary>
        /// 初始化视图
        /// </summary>
        private void InitView()
        {
            MasterHost.Instance.ViewModel = this;
           
            MasterHost.Instance.WindowManager = RadWindow;
            //数据库设计
            DatabaseExplorerViewModel = CreateView<DatabaseExplorerViewModel>(true);
            BuildUp(DatabaseExplorerViewModel);
            BuildUp(DatabaseExplorerViewModel.Model);
            //代码生成器
            CodeGeneratorViewModel = CreateView<CodeGeneratorViewModel>(true);
            BuildUp(CodeGeneratorViewModel);
            BuildUp(CodeGeneratorViewModel.Model);
            //过滤视图
            FilterDbSchemaViewModel = ViewModelFactory.GetModel<FilterDbSchemaViewModel>();

        }

        public override void OnLoad()
        {
            base.OnLoad();
            MasterHost.Instance.View = this.View as IMainView;
        }
        /// <summary>
        /// 查询表名视图
        /// </summary>
        public void FindTableByName()
        {
            if (!String.IsNullOrEmpty(FindName))
            {
                ViewFindDesignerItem(FindName);
            }

            DatabaseExplorerViewModel.IsSelected = true;
          
        }

        /// <summary>
        /// 调用IView接口的选择视图对象方法
        /// </summary>
        /// <param name="name"></param>
        private void ViewFindDesignerItem(string name)
        {
            var mv = this.View as IMainView;
            mv.SelectDesignerItem(name);
        }
        #endregion

        #region App菜单方法
       
        /// <summary>
        /// 连接数据库
        /// </summary>
        public void ConnectionDatabase()
        {
            var viewModel = ViewModelFactory.GetModel<SQLServerDialogViewModel>();
 
            BuildUp(viewModel);

            if (WindowManager.ShowDialog(viewModel).Value)
            {
                Model.ConnectionString = viewModel.Model.GetConnectionString();
                Model.SQLType = viewModel.Model.SQLType;
                Model.DatabaseName = viewModel.Model.DatabaseName;
            }
        }

        /// <summary>
        /// 同步数据库结构
        /// </summary>
        public async Task SyncDataBase()
        {
            if (string.IsNullOrEmpty(Model.ConnectionString))
            {
                RadWindow.ShowMessage("没有可用的数据库连接!");
                return;
            }
            //如果是打开文件项目则设置已载入的实体列表
            SerializableObservableCollection<DbEntity> loadedList = new SerializableObservableCollection<DbEntity>();
            if (Model.FilterEntitys != null && Model.FilterEntitys.Count > 0)
            {
                loadedList = Model.FilterEntitys;
            }
            //与数据库同步结构
            IsBusy = true;
            await Model.GetSchemas();
            Model.DisplayEntitys = Model.FilterEntitys;
           
            //同步到目录

            if (Model.DisplayEntitys != null && Model.DisplayEntitys.Count > 0)
                ViewFindDesignerItem(Model.DisplayEntitys[0].Name);

            CodeGeneratorViewModel.DisplayEntities = Model.FilterEntitys;
            IsBusy = false;
            loadFolder(loadedList);
            Model.Folders.OnChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
        }

        /// <summary>
        /// 连接IDE服务
        /// </summary>
        public void ConnectionIDE()
        {
            var viewModel = ViewModelFactory.GetModel<ConnectionVSIdeDialogViewModel>();
            RadWindow.ShowDialog(viewModel);
        }

        /// <summary>
        /// 生成文档
        /// </summary>
        public void GenerationDocument()
        {
            if (Model.IsOpen)
            {
                SaveFileDialog sfd = new SaveFileDialog();
                sfd.Filter = "*文档|*.doc";
                
                if (sfd.ShowDialog().Value == true)
                {
                    string fileName = sfd.FileName;
                    string itemName = System.IO.Path.GetFileNameWithoutExtension(fileName);
                    DocumentGeneratorService.CreateFile(itemName, Model.DatabaseName, Model.FilterEntitys.ToList(), fileName, DateTime.Now);
                    RadWindow.ShowMessage("文档生成完成！");
                }

               
            }
            else
            {
                RadWindow.ShowMessage("项目为空时，不能输出数据库文档！");
            }
        }


        #endregion

        #region 目录树方法

        /// <summary>
        /// 创建子文件夹
        /// </summary>
        public void CreateFolder(FolderInfo info)
        {

            var folderName = RadWindow.Prompt("请输入文件夹名称:");
            if (!string.IsNullOrEmpty(folderName))
            {
                Model.CreateChildrenFolder(info, folderName);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public void RemoveFolder(FolderInfo parent, FolderInfo info)
        {
            if (Model.RemoveChildrenFolder(parent, info))
            {

            }
            else
            {
                RadWindow.ShowMessage("要删除的文件夹必须是空的！");
            }
        }


        /// <summary>
        /// 目录单击事件，绑定选择目录下的所有实体
        /// </summary>
        /// <param name="info"></param>
        public async void OnNoteClick(FolderInfo info)
        {
           IsBusy = true;
          
           await TaskEx.Run(() => {
                if(info.InfoType=="Root")   //根目录
                {
                    Model.DisplayEntitys = Model.FilterEntitys;
                }
                else
                {
                    var entitys = new SerializableObservableCollection<DbEntity>();
                    getLoopFolderEntityList(info, entitys);
                    Model.DisplayEntitys = entitys;
                }
            });
           await TaskEx.Delay(650);
           IsBusy = false;
           if (Model.DisplayEntitys != null && Model.DisplayEntitys.Count > 0)
               ViewFindDesignerItem(Model.DisplayEntitys[0].Name);

        }

        /// <summary>
        /// 查找子目录下的所有实体
        /// </summary>
        private void getLoopFolderEntityList(FolderInfo parent, SerializableObservableCollection<DbEntity> list)
        {
            foreach (var entity in parent.TableCollection)
            {
                list.Add(entity);
            }

            foreach (var folder in parent.FolderCollection)
            {
                getLoopFolderEntityList(folder, list);
            }

        }


        /// <summary>
        /// 选择实体在图形界面中
        /// </summary>
        /// <param name="entity"></param>
        public void OnEntityNodeSelected(DbEntity entity)
        {
            this.ViewFindDesignerItem(entity.Name);
        }

        /// <summary>
        /// 同步到目录
        /// </summary>
        private void loadFolder(SerializableObservableCollection<DbEntity> loadedEntityList)
        {

            var tableRoot = Model.Folders[0].FolderCollection[0];
            var viewRoot = Model.Folders[0].FolderCollection[1];
            var proRoot = Model.Folders[0].FolderCollection[2];

            var root = Model.Folders[0];
            loadSubEntity(root, loadedEntityList);

            var tables = Model.FilterEntitys.Where(t => { return !loadedEntityList.Any(l => l.Name == t.Name) && t.EntityViewType == EntityType.Table; });
            foreach (var table in tables)
            {
                tableRoot.TableCollection.Add(table);
            }


            var views = Model.FilterEntitys.Where(t => { return !loadedEntityList.Any(l => l.Name == t.Name) && t.EntityViewType == EntityType.View; });
            foreach (var view in views)
            {
                viewRoot.TableCollection.Add(view);
            }

            var pros = Model.FilterEntitys.Where(t => { return !loadedEntityList.Any(l => l.Name == t.Name) && t.EntityViewType == EntityType.StoredProcedure; });
            foreach (var pro in pros)
            {
                proRoot.TableCollection.Add(pro);
            }

        }
        /// <summary>
        /// 载入目录实体(递归)
        /// </summary>
        /// <param name="parent"></param>
        /// <param name="loaded"></param>
        private void loadSubEntity(FolderInfo parent, SerializableObservableCollection<DbEntity> loaded)
        {
            foreach (var name in parent.TableNames)
            {
                var entity = Model.FilterEntitys.FirstOrDefault(t =>
                {
                    return !loaded.Any(l => l.Name == name) && t.Name == name;
                });
                if (entity != null)
                {
                    loaded.Add(entity);
                    parent.TableCollection.Add(entity);
                }

                if (!Model.FilterEntitys.Any(t => t.Name == name))
                {
                    var removeEntity = parent.TableCollection.First(t => t.Name == name);
                    parent.TableCollection.Remove(removeEntity);
                }
            }

        

            foreach (var folder in parent.FolderCollection)
            {
                loadSubEntity(folder, loaded);
            }

        }




        #endregion

        #region 文件系统操作
        /// <summary>
        /// 保存到文件 
        /// </summary>
        public void Save()
        {
            if (Model.IsOpen)
            {
                SaveFileDialog sfd = new SaveFileDialog();
                sfd.Filter = "*.xml|*.xml";
                if (sfd.ShowDialog().Value == true)
                {
                    string fileName = sfd.FileName;
                    string xml = Model.Folders.Serializer();
                    string entitysXML = Model.Tables.Serializer();
                    string filterXml = FilterDbSchemaViewModel.Model.GetSelectedNames().Serializer();
                    File.WriteAllText(fileName, xml, Encoding.Default);
                    File.WriteAllText(fileName + "_entity", entitysXML);
                    File.WriteAllText(fileName + "_filter", filterXml);
                    var bytes = ObjectHelper.SerializeObject(Model.Schema);
                    File.WriteAllBytes(fileName + "_schema", bytes);
                    Model.Log.Write("保存文件成功...."+ fileName);
                }
            }
            else
            {
                Model.Log.Write("还没有项目被打开，不能保存数据。");
                RadWindow.ShowMessage("还没有项目被打开，不能保存数据。");
            }
        }
        /// <summary>
        /// 新建，清空当前任务
        /// </summary>
        public void New()
        {
            if (RadWindow.ShowConfirm("新建操作会清空现有内容，确定要执行此操作吗?") == true)
            {
                if (Model.Folders != null)
                {
                    Model.Folders.Clear();
                    Model.Folders.OnChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
                }
                Model.Folders = null;
                if (Model.Tables != null)
                {
                    Model.Tables.Clear();
                }
                Model.Tables = null;
                if (Model.DisplayEntitys != null)
                {
                    Model.DisplayEntitys.Clear();
                    Model.DisplayEntitys.OnChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
                }
                if (Model.FilterEntitys != null)
                {
                    Model.FilterEntitys.Clear();
                    Model.FilterEntitys.OnChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
                }
                Model.FilterEntitys = null;
                Model.DisplayEntitys = null;
                Model.IsOpen = false;
                Model.ConnectionString = null;

                this.DatabaseExplorerViewModel.Close();
                MasterHost.Instance.Tables = null;
                ServiceManager.services.Clear();
                MasterHost.Instance.View.ShowExplorer();
                Model.Log.Write("新建任务完成，欢迎使用......");
            }
        }
        /// <summary>
        /// 从文件系统打开
        /// </summary>
        public async void Open()
        {
            OpenFileDialog sfd = new OpenFileDialog();
            sfd.Filter = "*.xml|*.xml";
            if (sfd.ShowDialog().Value == true)
            {
                IsBusy = true;
                Model.Log.Write("正在打开文件......");
                await TaskEx.Run(() => {
                    string fileName = sfd.FileName;
                    Model.Folders = File.ReadAllText(fileName, Encoding.Default).Deserialize<SerializableObservableCollection<FolderInfo>>();

                    Model.Tables = File.ReadAllText(fileName + "_entity").Deserialize<SerializableObservableCollection<DbEntity>>();
                    Model.Schema = ObjectHelper.DeserializeObject(File.ReadAllBytes(fileName + "_schema")) as DatabaseSchema;
                    var filterNames = File.ReadAllText(fileName + "_filter").Deserialize<List<string>>();
                    Model.SelectedItemNames = filterNames;
                    Model.FilterEntitys = new SerializableObservableCollection<DbEntity>();
                    Model.Log.Write("打开SQL-MAP文件......");
                    DatabaseExplorerViewModel.OpenForFile(Path.Combine(Path.GetDirectoryName(fileName), "sqlmap.sqlm"));
                    
                    foreach (var item in Model.Tables)
                    {
                        if (filterNames.Contains(item.Name))
                            Model.FilterEntitys.Add(item);
                    }
                    Model.DisplayEntitys = Model.FilterEntitys;
                    
                    Model.IsOpen = true;

                    DatabaseMetaService isn = new DatabaseMetaService();
                    isn.Schema = Model.Schema;
                    isn.TableMetas = Model.Tables;
                    isn.SQLType = Model.SQLType;
                    Model.Log.Write("加载数据库连接配置文件......");
                    var connectionInfo = new SQLServerDialogInfo();
                    try
                    {
                        connectionInfo.LoadProperties();
                        isn.ConnectionString = connectionInfo.GetConnectionString();
                        Model.SQLType = connectionInfo.SQLType;
                        Model.DatabaseName = connectionInfo.DatabaseName;
                        Model.ConnectionString = isn.ConnectionString;
                    }
                    catch { }

                    isn.Process(Model.Tables.ToDictionary(k => k.Name));
                    ServiceManager.GetService(isn.GetType(), isn);
                    Model.Log.Write("加载元数据，生成目录......");
                    var loadedEntityList = new SerializableObservableCollection<DbEntity>();
                    loadFolder(loadedEntityList);
                });
              
                IsBusy = false;
                if (Model.DisplayEntitys != null && Model.DisplayEntitys.Count > 0)
                    ViewFindDesignerItem(Model.DisplayEntitys[0].Name);
                Model.Folders.OnChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));

                
                CodeGeneratorViewModel.DisplayEntities = Model.FilterEntitys;
                MasterHost.Instance.Tables = Model.FilterEntitys.ToList();
                MasterHost.Instance.View.ShowExplorer();
                Model.Log.Write("加载任务完成......");
            }

        }
        #endregion

        #endregion
    }
}
